<?php
/**
 *
 * to manage the session items
 *
 * support mutiple storages and items
 *
 * @author Ben
 * @package Aramisauto
 */
class WacStorage
{
    /*
     * user object
     */
    public $user = null;

    /**
     * session name
     * @access public
     * @var string
     */
    public $sessionName = 'WacStorage';

    /**
     * session value
     * @access public
     * @var string
     */
    public $sessionValue = '';

    /**
     * storages
     * @access public
     * @var array
     */
    public $storages = array();

    /**
     * error code
     * @access public
     * @var integer
     */
    public $errCode = 0;

    /**
     * is empty
     * @access public
     * @var bool
     */
    public $isEmpty = true;


    /**
     * current shop id
     * @access public
     * @var integer
     */
    public $currentStorageId = 0;

    /**
     * at the beginning, use this id as shop id
     * @access public
     * @var integer
     */
    public $defaultStorageId = 0;

    /**
     * debug
     * @access public
     * @var bool
     */
    public $debug = true;

    /**
     * construct method
     *
     */
    public function __construct()
    {
        $this->user = sfContext::getInstance()->getUser();

        if ($this->user->hasAttribute($this->sessionName))
        {
//            $this->storages = unserialize(stripslashes($this->user->getAttribute($this->sessionName)));
            $this->storages = $this->user->getAttribute($this->sessionName);
            if (gettype($this->storages) == "array" && count($this->storages) > 0){
                $this->isEmpty = false;
            }
            else{
                $this->isEmpty = true;
            }
        } else {
            $this->isEmpty = true;
        }

        if ($this->isEmpty == false){
            foreach ($this->storages as $storageId => $shop_detail) {
                $this->currentStorageId = $storageId;
                break;
            }
        }
        
        if ($this->isEmpty) { // initializing the shop, for only one shop
            $params = $this->createInfoStructure();
            $this->addStorage($this->defaultStorageId, $params);
        }
    }

    /**
     * create single instance of class
     *
     * @return object
     */
    public static function create()
    {
        // static associative array containing the real objects, key is classname
        static $instances = array();
        static $_count = 0;
        // get classname
        $class = __CLASS__;
        if (! array_key_exists($class, $instances)) {
            // does not yet exist, save in array
            $instances[$class] = new $class();
        }
        return $instances[$class];
    }

    /**
     * create shop structure
     *
     * @return array
     */
    public function createStorageStructure()
    {
        $tmpInfo      = $this->createInfoStructure();
        $tmpStorage = array(
                         'items'  => array(),
                         'info'   => $tmpInfo,
                   );
        return $tmpStorage;
    }

    /**
     * creat info structure
     *
     * @return array
     */
    public function createInfoStructure()
    {
        $tmpInfo = array('id'=>'', 'memo'=>'', 'itemsCount'=>0);
        return $tmpInfo;
    }

    /**
     * create item structure
     *
     * @return array
     */
    public function createItemStructure()
    {
        //vehicleKind => cohibaVehicle / robustoVehicle / stockVehicle
        $tmpItem = array('id'=>"", 'name'=>"", 'value'=>"", 'label'=>"");
        return $tmpItem;
    }

    /**
     * add shop
     *
     * @param integer $id
     * @param array $params = array() as createInfoStructure()
     * @return bool
     */
    public function addStorage($id, $infoParams=array())
    {
        if ($this->isEmpty || ! array_key_exists($id, $this->storages)) {
            $this->storages[$id] = $this->createStorageStructure();
            $this->storages[$id]['info']= $infoParams;
        }
        else {
            $this->errCode = 1;
        }
        
        $this->serializeSession();
        if (! $this->user->hasAttribute($this->sessionName)) {
            trigger_error('could not set session: ' . $this->sessionName . ' session value is: ' . $this->sessionValue, E_USER_ERROR);
        }

        $this->isEmpty = false;
        
        if ($this->errCode != 0) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * update shop
     *
     * @param integer $id
     * @param array $params
     */
    public function updateStorage($id, $infoParams)
    {
        if (isset($this->storages[$id])) {
            if (is_array($params)) {
                $this->storages[$id]['info'] = $infoParams;
            }
        }
        $this->serializeSession();
        if (! $this->user->hasAttribute($this->sessionName)) {
            trigger_error('could not set session: ' . $this->sessionName . ' session value is: ' . $this->sessionValue, E_USER_ERROR);
        }
    }

    /**
     * remove shop
     *
     * @param integer $id
     */
    public function removeStorage($id)
    {
        if ($this->isExistedStorage($id)) {
            if (isset($this->storages[$id])) {
                unset($this->storages[$id]);
            }
        }
        if (count($this->storages) == 0) {
            $this->isEmpty = true;
        }
        $this->serializeSession();
    }

    /**
     * add item
     *
     * @param integer $storageId
     * @param array $params
     * @return bool
     */
    public function addItem($storageId, $params)
    {
        if ($this->isExistedStorage($storageId)) {
           $this->addCommonItem($storageId, $params);
        }
        $this->serializeSession();
        if (! $this->user->hasAttribute($this->sessionName)) {
            trigger_error('could not set session: ' . $this->sessionName . ' session value is: ' . $this->sessionValue, E_USER_ERROR);
        }
        if ($this->errCode != 0) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * remove item by idx
     *
     * @param integer $storageId
     * @param integer ['order']['itemsCount']
     * @param bool $reindex
     */
    protected function removeItem($storageId, $idx, $reindex = false)
    {
        if ($this->isExistedStorage($storageId)) {
            if (isset($this->storages[$storageId]['items'][$idx])) {
                $this->storages[$storageId]['info']['itemsCount'] --;
                unset($this->storages[$storageId]['items'][$idx]);
            }
            if (count($this->storages[$storageId]['items']) == 0) {
                $this->storages[$storageId]['info']['itemsCount'] = 0;
                //				unset($this->storages[$storageId]);
            } else {
                if ($reindex) {
                    $this->reindexStorageItems($storageId);
                }
            }
        }
        $this->serializeSession();
    }

    /**
     * get item index
     *
     * @param integer $storageId
     * @param integer $itemId
     * @return integer
     */
    public function getItemIndex($storageId, $itemId)
    {
        $index = -1;
        $i = 0;
        if ($this->isExistedStorage($storageId)) {
            if (count($this->storages[$storageId]['items']) > 0) {
                foreach ($this->storages[$storageId]['items'] as $theItem) {
                    if ($theItem['id'] == $itemId) {
                        $index = $i;
                        break;
                    }
                    $i ++;
                }
            }
        }
        return $index;
    }

    /**
     * get shop item by index
     *
     * @param integer $storageId
     * @param integer $index
     * @return array
     */
    public function getStorageItemByIndex($storageId, $index)
    {
        if ($this->isExistedStorage($storageId)) {
            if (array_key_exists($index, $this->storages[$storageId]['items'])) {
                return $this->storages[$storageId]['items'][$index];
            } else {
                return NULL;
            }
        } else {
            return NULL;
        }
    }

    /**
     * remove item by item id
     *
     * @param integer $storageId
     * @param integer $itemId
     * @param bool $reindex
     */
    public function removeItemByItemId($storageId, $itemId, $reindex = false)
    {
        $index = $this->getItemIndex($storageId, $itemId);
        if ($index > -1) {
            $this->removeItem($storageId, $index, $reindex);
        }
    }

    /**
     * reindex shop items
     *
     * @param integer $storageId
     */
    public function reindexStorageItems($storageId)
    {
        if ($this->isExistedStorage($storageId)) {
            $this->storages[$storageId]['items'] = array_values($this->storages[$storageId]['items']);
        }
        $this->serializeSession();
    }

    /**
     * sort items
     *
     * @param integer $storageId
     * @param string $sort_by
     * @param bool $serializeFlag
     */
    public function sortItems($storageId, $sort_by = 'dateTime', $serializeFlag = false)
    {
        if ($this->isExistedStorage($storageId)) {
            $itemCount = count($this->storages[$storageId]['items']);
            $tmpItem = array();
            if ($itemCount > 0) {
                for ($i = $itemCount; $i > 0; $i --) {
                    for ($j = 0; $j < $i; $j ++) {
                        $tmpItem = $this->storages[$storageId]['items'][$j];
                        if (isset($this->storages[$storageId]['items'][$j + 1])) {
                            if ($sort_by === 'dateTime') {
                                if (($this->storages[$storageId]['items'][$j + 1]['dateStart'] < $this->storages[$storageId]['items'][$j]['dateStart']) || ($this->storages[$storageId]['items'][$j + 1]['dateStart'] == $this->storages[$storageId]['items'][$j]['dateStart'] && strtotime($this->storages[$storageId]['items'][$j + 1]['timeStart']) < strtotime($this->storages[$storageId]['items'][$j]['timeStart']))) {
                                    $this->storages[$storageId]['items'][$j] = $this->storages[$storageId]['items'][$j + 1];
                                    $this->storages[$storageId]['items'][$j + 1] = $tmpItem;
                                }
                            }
                        }
                    }
                }
            }
            if ($serializeFlag) {
                $this->serializeSession();
            }
        }
    }

    /**
     * sort storages items
     *
     * @param string $sort_by
     */
    public function sortStoragesItems($sort_by = 'dateTime')
    {
        if (! $this->isEmpty) {
            foreach ($this->storages as $theStorage) {
                $this->sortItems($theStorage['info']['id'], $sort_by, false);
            }
            $this->serializeSession();
        }
    }

    /**
     * remove all items
     *
     * @param integer $storageId
     */
    public function removeAllItems($storageId)
    {
        if ($this->isExistedStorage($storageId)) {
            if (isset($this->storages[$storageId]['items'])) {
                $this->storages[$storageId]['info']['itemsCount'] = 0;
                if (count($this->storages[$storageId]['items']) > 0) {
                    $this->storages[$storageId]['items'] = array();
                }
            }
        }
        $this->serializeSession();
    }

    /**
     * add common item
     *
     * @param integer $storageId
     * @param integer $params
     */
    public function addCommonItem($storageId, $itemParams)
    {
        if ($this->isExistedStorage($storageId)) {
//            $tmpItem = $this->createItemStructure();
            $tmpItem = $itemParams;
            
            if (! $this->isExistedStorageItem($storageId, $tmpItem)) {
                $this->storages[$storageId]['info']['itemsCount'] ++;
                $this->storages[$storageId]['items'][] = $tmpItem;
            }
        }
    }

    /**
     * is shop existed
     *
     * @param integer $id
     * @return integer/bool
     */
    public function isExistedStorage($id)
    {
        if (! $this->isEmpty) {
            return array_key_exists($id, $this->storages);
        } else
            return false;
    }

    /**
     * is shop item existed
     *
     * @param integer $storageId
     * @param array $itemParams
     * @return bool
     */
    public function isExistedStorageItem($storageId, $itemParams)
    {
        if (isset($this->storages[$storageId]['items'])) {
            $flag = false;
            if (count($this->storages[$storageId]['items']) > 0) {
                foreach ($this->storages[$storageId]['items'] as $theItem) {
                    if ($theItem['id'] == $itemParams['id']) {
                        $flag = true;
                        break;
                    }
                }
            }
            return $flag;
        } else
            return false;
    }

    /**
     * reset shop
     *
     */
    public function resetStorage()
    {
        reset($this->storages);
    }

    /**
     * count shop
     *
     * @return integer
     */
    public function countStorage()
    {
        if (!$this->isEmpty) {
            return count($this->storages);
        } else {
            return 0;
        }
    }

    /**
     * get count of shop items
     *
     * @param integer $storageId
     * @return integer
     */
    public function getStorageItemsCount($storageId)
    {
        if ($this->isExistedStorage($storageId)) {
            return $this->storages[$storageId]['info']['itemsCount'];
        } else {
            return 0;
        }
    }

    /**
     * remove all storages
     *
     */
    public function removeAllStorages()
    {
        $this->storages = array();
        if ($this->user->hasAttribute($this->sessionName)) {
           $this->user->getAttributeHolder()->remove($this->sessionName);
        }
        $this->isEmpty = true;
    }

    /**
     * set name of cart
     *
     * @param string $value
     */
    public function setCartName($value)
    {
        $this->sessionName = $value;
    }

    /**
     * print debug info
     *
     * @param bool $varFlag
     * @return string
     */
    public function printOut($varFlag = false)
    {
        if ($this->debug) {
            $tmpStr = '';
            $tmpStr .= "<h3>{$this->sessionName} Debug Info:</h3><br/>" . str_repeat('=', 100) . '<br/>';
            $tmpStr .= nl2br(print_r($this->storages, true));
            if (! $varFlag) {
                echo $tmpStr;
            } else {
                return $tmpStr;
            }
        }
    }

    /**
     * add shashes to data
     *
     * @param array $val
     * @param string $key
     */
    public function addSlashesData(&$val, $key)
    {
        if (is_array($val)) {
            array_walk($val, array(&$this, 'addSlashesData'));
        } else {
            $val = addslashes($val);
        }
    }

    /**
     * strip slashes from data
     *
     * @param array $val
     * @param string $key
     */
    public function stripSlashesData(&$val, $key)
    {
        if (is_array($val)) {
            array_walk($val, array(&$this, 'stripSlashesData'));
        } else {
            $val = stripslashes($val);
        }
    }

    /**
     * serialize session
     *
     */
    public function serializeSession()
    {
//        $this->sessionValue = serialize($this->storages);
//        $this->user->setAttribute($this->sessionName, $this->sessionValue);
        $this->user->setAttribute($this->sessionName, $this->storages);
    }

    /**
     * get list of existed item id of shop
     *
     * @param integer $storageId
     * @param bool $isToString
     * @return array / string
     */
    public function getExistedItemIds($storageId, $isToString = false)
    {
        $tmpArr = array();
        if ($this->isExistedStorage($storageId)) {
            foreach ($this->storages[$storageId]["items"] as $theItem) {
                $tmpArr[] = $theItem["id"];
            }
        }
        if ($isToString) {
            return implode(',', $tmpArr);
        } else {
            return $tmpArr;
        }
    }

    /**
     * get item string with JSON format
     *
     * @param integer $storageId
     * @return string
     */
    public function getStorageJsonItemsString($storageId)
    {
        if ($this->isExistedStorage($storageId)) {
            return json_encode($this->storages[$storageId]['items']);
        }
    }
}
?>